#include "Inf_es8311.h"

#define ES8311_I2C_SDA 0
#define ES8311_I2C_SCL 1

#define I2S_MCK_PIN GPIO_NUM_3
#define I2S_BCK_PIN GPIO_NUM_2
#define I2S_DI_PIN GPIO_NUM_4
#define I2S_WS_PIN GPIO_NUM_5
#define I2S_DO_PIN GPIO_NUM_6
#define PA_EN_PIN 46

i2c_master_bus_handle_t i2c_bus_handle;

i2s_chan_handle_t mic_channel_handle;
i2s_chan_handle_t speak_channel_handle;

esp_codec_dev_handle_t codec_dev;
// 初始化I2C
void Inf_es8311_i2c_init(void)
{
    i2c_master_bus_config_t i2c_bus_config = {0};
    i2c_bus_config.clk_source = I2C_CLK_SRC_DEFAULT;
    i2c_bus_config.i2c_port = I2C_NUM_0;
    i2c_bus_config.scl_io_num = ES8311_I2C_SCL;
    i2c_bus_config.sda_io_num = ES8311_I2C_SDA;
    i2c_bus_config.glitch_ignore_cnt = 7;
    i2c_bus_config.flags.enable_internal_pullup = true;
    i2c_new_master_bus(&i2c_bus_config, &i2c_bus_handle);
}

void Inf_es8311_i2s_init(void)
{
    /* 1. 选择i2s的外设 */
    i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_0, I2S_ROLE_MASTER);

    /* 2. i2s的配置 */
    i2s_std_config_t std_cfg = {
        .clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(16000),
        .slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(16, I2S_SLOT_MODE_MONO),
        .gpio_cfg = {
            .mclk = I2S_MCK_PIN,
            .bclk = I2S_BCK_PIN,
            .ws = I2S_WS_PIN,
            .dout = I2S_DO_PIN,
            .din = I2S_DI_PIN,
        },
    };
    /* 3. 创建i2s通道 */
    i2s_new_channel(&chan_cfg, &speak_channel_handle, &mic_channel_handle);

    /* 4. 初始化输出通道 */
    i2s_channel_init_std_mode(speak_channel_handle, &std_cfg);

    /* 5. 初始化输入通道 */
    i2s_channel_init_std_mode(mic_channel_handle, &std_cfg);

    /* 6. 使能输出和输入通道 */
    i2s_channel_enable(speak_channel_handle);
    i2s_channel_enable(mic_channel_handle);
}

void Inf_es8311_init(void)
{
    /* 1. 创建编解码器的数据接口 */
    audio_codec_i2s_cfg_t i2s_cfg = {
        .rx_handle = mic_channel_handle,
        .tx_handle = speak_channel_handle};
    const audio_codec_data_if_t *data_if = audio_codec_new_i2s_data(&i2s_cfg);

    /* 2. 创建编解码器的控制接口 */
    audio_codec_i2c_cfg_t i2c_cfg = {
        .bus_handle = i2c_bus_handle,
        .addr = ES8311_CODEC_DEFAULT_ADDR,
        .port = I2C_NUM_0};
    const audio_codec_ctrl_if_t *out_ctrl_if = audio_codec_new_i2c_ctrl(&i2c_cfg);

    /* 3. 创建gp接口 */
    const audio_codec_gpio_if_t *gpio_if = audio_codec_new_gpio();

    /* 4. 创建编解码器接口 */
    es8311_codec_cfg_t es8311_cfg = {
        .codec_mode = ESP_CODEC_DEV_WORK_MODE_BOTH, // 双工模式
        .ctrl_if = out_ctrl_if,                     // 控制接口
        .gpio_if = gpio_if,                         // gpio接口
        .pa_pin = PA_EN_PIN,                        // PA_EN_PIN
        .use_mclk = true,                           // 使用mclk
        .digital_mic = false                        // 不使用数字麦克风
    };
    const audio_codec_if_t *out_codec_if = es8311_codec_new(&es8311_cfg);

    /* 5. 创建编解码设备 */
    esp_codec_dev_cfg_t dev_cfg = {
        .codec_if = out_codec_if,             // codec interface from es8311_codec_new
        .data_if = data_if,                   // data interface from audio_codec_new_i2s_data
        .dev_type = ESP_CODEC_DEV_TYPE_IN_OUT // codec support both playback and record
    };
    codec_dev = esp_codec_dev_new(&dev_cfg);

    // 音箱音量控制
    esp_codec_dev_set_out_vol(codec_dev, 60.0);

    /* 6. 打开编解码设备 */
    esp_codec_dev_sample_info_t fs = {
        .sample_rate = 16 * 1000, // 采样率
        .channel = 1,             // 采样通道
        .bits_per_sample = 16,    // 采样深度
        .mclk_multiple = 256,     // 计算主时钟 sample_rate * 256
        .channel_mask = ESP_CODEC_DEV_MAKE_CHANNEL_MASK(0)};
    esp_codec_dev_open(codec_dev, &fs);
}

/**
 * @brief 初始化ES8311音频模块
 */
void Inf_es8311_adio_init(void)
{
    Inf_es8311_i2c_init();
    Inf_es8311_i2s_init();
    Inf_es8311_init();
    esp_codec_dev_set_in_gain(codec_dev, 30.0);
}
/**
 * @brief 播放音频数据
 * @param data 音频数据
 * @param len 音频数据长度
 * @return ESP_CODEC_DEV_OK: Write success
 *         ESP_CODEC_DEV_INVALID_ARG: Invalid arguments
 *         ESP_CODEC_DEV_NOT_SUPPORT: Codec not support
 *         ESP_CODEC_DEV_WRONG_STATE: Driver not open yet
 *         ESP_CODEC_DEV_DRV_ERR: Driver error
 */
int Inf_es8311_WriteData(uint8_t data[], int len)
{
    if (data && codec_dev && len)
    {
        return esp_codec_dev_write(codec_dev, data, len);
    }
    return ESP_CODEC_DEV_DRV_ERR;
}

/**
 * @brief 读取音频数据
 * @param data 音频数据
 * @param len 音频数据长度
 * @return ESP_CODEC_DEV_OK: Read success
 *         ESP_CODEC_DEV_INVALID_ARG: Invalid arguments
 *         ESP_CODEC_DEV_NOT_SUPPORT: Codec not support
 *         ESP_CODEC_DEV_WRONG_STATE: Driver not open yet
 *         ESP_CODEC_DEV_DRV_ERR: Driver error
 */
int Inf_es8311_ReadData(uint8_t data[], int len)
{
    if (data && codec_dev && len)
    {
        return esp_codec_dev_read(codec_dev, data, len);
    }
    return ESP_CODEC_DEV_DRV_ERR;
}